/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frtask_mng.h                                       */
/*  NOTE      = 任务管理                                           */
/*  DATE      = 2014/10/20                                         */
/*******************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include "frcomm.h"
#include "frlog.h"
#include "frmem.h"
#include "frlist.h"
#include "conntrack.h"
#include "frame.h"
#include "frct_mng.h"

//单位usec
#define APM_LOCK_TIMEOUT   10000

FR_STATIC int  g_i_task_lock = FR_NO;
FR_STATIC Frlist_header g_lst_hdr_task;

/*******************************************************************************
*  FUNC     :  节点释放
*  ARGS     :  p_st_node  (Frlist_node *)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __task_mng_list_node_free(Frlist_node *p_st_node)
{
    Conntrack *p_st_ct=NULL;
    
    if(p_st_node == NULL)
        return;
    
    p_st_ct = (Conntrack *)FRLIST_GET_NODE_DATA(p_st_node);
    frct_put(p_st_ct);
    return;
}

/*******************************************************************************
*  FUNC     :  节点内容出力
*  ARGS     :  p_st_node       (Frlist_node *)
            :  p_outbuff       (出力内容指针)
            :  ui_buff_size    (出力内容空间)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __task_mng_list_node_show(Frlist_node* node, char *p_outbuff, unsigned int ui_buff_size)
{
    if(ui_buff_size <= 0 )
        return;

    snprintf(p_outbuff, ui_buff_size, "%p:", node->data);
    return;
}

/*******************************************************************************
*  FUNC     :  任务管理队列初始化
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
int frtask_mng_init(void)
{
    frlist_header_init(&g_lst_hdr_task);
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  任务管理队列释放
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frtask_mng_destory(void)
{
    frlist_remove_all(&g_lst_hdr_task, __task_mng_list_node_free);
    return;
}

/*******************************************************************************
*  FUNC     :  ct加入到任务队列
*  ARGS     :  p_st_ct (Conntrack *)
*  RTN      :
*  NOTE     :
*******************************************************************************/
int frtask_add(Conntrack *p_st_ct)
{
    int i_ret = FR_FAIL;
    Frlist_node *p_st_node=NULL;
    
    if(p_st_ct == NULL)
        return i_ret;
    
    //取得锁
    while (!__sync_bool_compare_and_swap(&g_i_task_lock, FR_NO, FR_YES) )
    {
        if(!g_i_flag_run)
            return i_ret;

        usleep(APM_LOCK_TIMEOUT);
    }
    
    p_st_node = frlist_node_create(p_st_ct);
    if(p_st_node == NULL)
        goto END;
    
    frlist_push(&g_lst_hdr_task, p_st_node);
    i_ret = FR_SUCC;
END:
    //释放锁
    __sync_fetch_and_sub(&g_i_task_lock, FR_YES);
    return i_ret;
}

Conntrack *frtask_get(void)
{
    Conntrack *p_st_ct = NULL;
    Frlist_node *p_st_node=NULL;
    
    //获取数据
    do
    {
        //取得锁
        while (! __sync_bool_compare_and_swap(&g_i_task_lock, FR_NO, FR_YES) )
        {
            if(!g_i_flag_run)
                return NULL;
            usleep(APM_LOCK_TIMEOUT);
        }
    
        p_st_node = frlist_pop(&g_lst_hdr_task);
        //释放锁
        __sync_fetch_and_sub(&g_i_task_lock, FR_YES);

        if(p_st_node == NULL && g_i_flag_run)
            usleep(APM_LOCK_TIMEOUT);
    } while(p_st_node == NULL && g_i_flag_run);

    if(p_st_node)
    {
        p_st_ct = (Conntrack *)p_st_node->data;
        frfree(p_st_node);
    }

    return p_st_ct;
}

/*******************************************************************************
*  FUNC     :  获取task里保存的任务个数
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
int frtaskskb_counts(void)
{
    return frlist_size(&g_lst_hdr_task);
}

/*******************************************************************************
*  FUNC     :  出力当前task内容
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frtaskskb_output(char **pp_result)
{
    char *p_outbuff;
    int i_size = 1024000;
    
    p_outbuff = (char *)frmalloc(i_size);
    if(p_outbuff == NULL)
        return;
    
    *p_outbuff = '\0';
    frlist_show(&g_lst_hdr_task, p_outbuff, i_size, __task_mng_list_node_show);
    
    if(pp_result == NULL)
    {
        FRLOG_DEBUG("-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
        printf("output task data(count=%d)\n%s\n",frlist_size(&g_lst_hdr_task), p_outbuff);
        FRLOG_DEBUG("-*-*-*-*-*-*-*-*-*-*-*-*-*\n");

        frfree(p_outbuff);
    }
    else
        *pp_result = p_outbuff;

    return;
}
